/**
 * node 中的基本用法. 一些常用 API 用法.
 */

// node 中为了实现 I/O操作, 自己实现了一个 libuv 库(事件环的概念) => 异步操作 靠的多线程
// 服务端全局变量,原则是 global, 但是 node 在执行的时候,为了实现模块化, 会在
// 代码运行时, 外部包装一个函数, 这个函数在执行的时候, 会改变 this 指向.
// console.log(this); //=> {}
// console.dir(global, {showHidden: true});

// ================== 需要掌握的常用 API ====================

// Buffer __dirname __filename exports module process require

// 后面的 五个属性, 都可以直接访问, 在文件中, 但是不能通过 global 来获取.


/**
 * ==========  process: 需要掌握的属性 ========================
 *  1. platform:  识别运行的机器环境 windows=> win32   MAC => darwin
 *  2. nextTick
 *  3. cwd: current working directory(当前工作目录: 你在哪儿执行的这个文件)
 *  4. env
 *  5. argv
 */
// console.log(Object.keys(process));
// console.log(process.platform);

// cwd 获取执行命令时的路径. (执行命令的地方变了,这个路径就会改变.)
// console.log("-->", process.cwd());
//
//
// console.log(__filename); // 代表文件所在的位置, 是一个绝对位置
// console.log(__dirname); // 代表文件所在的目录. 是一个绝对路径

// 系统的环境变量: 在执行命令的时候, 可以去读取环境变量中的属性.
// 添加变量: 在 windows 中, 可以使用 set 命令来设置,  mac 用export  =>cross-env 这个包可以设置
// console.log("env ====>", process.env);


// argv 执行命令式, 所带的参数
// 1. 第一个代表可执行文件 node.exe
//2.  第二个是执行的那个文件
// console.log("process.argv -->>", process.argv.slice(2));
//
// let args = process.argv.slice(2)
// let userArgs = args.reduce((memo, current, index, arr) => {
//   if (current.includes("--")) {
//     memo[current.slice(2)] = arr[index + 1] || true
//   }
//   return memo
// }, {})


// commander 库.  常用的 库
// const {program} = require("commander")
//
// program.version("0.0.1")
// program.parse(process.argv)


//============== node 中的事件环 ===============
// node中的process.nextTick 是异步的, 把它叫做微任务, 但是不属于事件环的一部分.
//
// process.nextTick(() => { // 异步的, 把它叫成微任务.
//   console.log("nextTick");
// })
//
// // promise 也不属于 node 中的事件环.
// Promise.resolve().then(() => {
//   console.log("promise");
// })


// node 中自己实现了一个 事件环机制. (新版本的node 执行的结果和浏览器执行的结果一样) 但是底层实现的方式不太一样
// 对于浏览器, 宏任务只有一个队列,
// 对于node而言, setImmediate,setTimeout 创造了多个宏任务队列.


// node 和浏览器事件环的差异:  浏览器 1 个队列, node 多个队列
// 执行顺序都是 先执行 代码 -> node会清空 nextTick -> 清空微任务 => 再取出一个宏任务来执行
// 当浏览器到达 pool 阶段后, 如果 check 阶段为空, 而且 poll 里面也没有 io操作
// 此刻不会立即轮训, 会等待定时器到达时间, 重新执行. 或者有新的 io操作, 进入到 poll阶段中.





